// ===================================
// <copyright>
// This file is part of LABSMFController.
//
//    LABSMFController is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    LABSMFController is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with LABSMFController.  If not, see <http://www.gnu.org/licenses/>.
//    Copyright 2011 David Bakker
//
//</copyright>
// <author>David Bakker</author>
// <email>mailto:DavidFBakker@gmail.com</email>
// <created>Saturday, May 07, 2011</created>
// <lastedit>Saturday, May 07, 2011</lastedit>
// ===================================

using System.Threading;
using GHIElectronics.NETMF.Hardware;
using LABSMFController.LABS.Classses;
using LABSMFController.LABS.Devices;

namespace LABSMFController.LABS.Services
{

    #region Nested type: TemperatureService

    public class TemperatureServiceClass : BeerService
    {
        private const int RefeshInterval = 2000;
        private const int ErrorTimeOut = 5000;
        private const int Interval = 100;
        private static int _currentErrorInterval;
        private Thread _myThread;

        public override string Description { get; set; }

        internal static int MAXProbes = 3;


        public TempProbe[] TempProbes;

        public  string GetTempProbesClientOutPut()
        {
            string ret = "HEADER:TempProbe:" + TempProbes[0].Header + ";";
            for (int c = 0; c < MAXProbes; c++)
            {
                ret = ret + "\r\n" + TempProbes[c].GetClientOutPut();
            }
            return ret;
        }

        public  void SetUpTemp()
        {
            TempProbes = new TempProbe[MAXProbes];
            Location.Setup();
            TempProbes[Location.HLT] = new TempProbe
            {
                Location = Location.Names[Location.HLT],
                LocationID = Location.HLT
            };
            TempProbes[Location.HLT].Description = TempProbes[Location.HLT].Location + " temp";
            //TempProbes[KettleLocation.HLT].ByteAddress[0] = 16;
            //TempProbes[KettleLocation.HLT].ByteAddress[1] = 136;
            //TempProbes[KettleLocation.HLT].ByteAddress[2] = 36;
            //TempProbes[KettleLocation.HLT].ByteAddress[3] = 211;
            //TempProbes[KettleLocation.HLT].ByteAddress[4] = 1;
            //TempProbes[KettleLocation.HLT].ByteAddress[5] = 8;
            //TempProbes[KettleLocation.HLT].ByteAddress[6] = 0;
            //TempProbes[KettleLocation.HLT].ByteAddress[7] = 3;

            TempProbes[Location.MLT] = new TempProbe
            {
                Location = Location.Names[Location.MLT],
                LocationID = Location.MLT
            };
            TempProbes[Location.MLT].Description = TempProbes[Location.MLT].Location + " temp";
            //TempProbes[KettleLocation.MLT].ByteAddress[0] = 16;
            //TempProbes[KettleLocation.MLT].ByteAddress[1] = 232;
            //TempProbes[KettleLocation.MLT].ByteAddress[2] = 28;
            //TempProbes[KettleLocation.MLT].ByteAddress[3] = 211;
            //TempProbes[KettleLocation.MLT].ByteAddress[4] = 1;
            //TempProbes[KettleLocation.MLT].ByteAddress[5] = 8;
            //TempProbes[KettleLocation.MLT].ByteAddress[6] = 0;
            //TempProbes[KettleLocation.MLT].ByteAddress[7] = 122;

            TempProbes[Location.BK] = new TempProbe
            {
                Location = Location.Names[Location.BK],
                LocationID = Location.BK
            };
            TempProbes[Location.BK].Description = TempProbes[Location.BK].Location + " temp";
            //TempProbes[KettleLocation.BK].ByteAddress[0] = 16;
            //TempProbes[KettleLocation.BK].ByteAddress[1] = 5;
            //TempProbes[KettleLocation.BK].ByteAddress[2] = 64;
            //TempProbes[KettleLocation.BK].ByteAddress[3] = 211;
            //TempProbes[KettleLocation.BK].ByteAddress[4] = 1;
            //TempProbes[KettleLocation.BK].ByteAddress[5] = 8;
            //TempProbes[KettleLocation.BK].ByteAddress[6] = 0;
            //TempProbes[KettleLocation.BK].ByteAddress[7] = 173;
        }


        public override void Configure()
        {
            IsActive = false;
            Description = "Temperature Service";
            _currentErrorInterval = 0;
            SetUpTemp();
        }


        public override void Stop()
        {
            _myThread.Abort();
            IsActive = false;
        }

        public override void Start()
        {
            BeerProgram.Log(Description + " Starting");
            IsActive = true;
            _myThread = new Thread(TempThread);
            _myThread.Start();
        }

        private void TempThread()
        {
            while (true)
            {
                if (!Description.Equals(""))
                {
                    for (int c = 0; c < MAXProbes; c++)
                    {
                        TempProbes[c].Temperature = UpdateTemp(TempProbes[c].LocationID,
                                                                           EnableDebug);
                        if (EnableDebug)
                            BeerProgram.Log(TempProbes[c].Location + " " +
                                            TempProbes[c].Temperature);
                    }
                }
                Thread.Sleep(RefeshInterval);
            }
        }


        public override string Status()
        {
            return "Is Active : " + IsActive;
        }

        private int UpdateTemp(int tempLocation, bool debug)
        {
            const int tempf = BeerDevices.TempError;
            _currentErrorInterval = 0;
            OneWire tempOneWire;

            switch (tempLocation)
            {
                case Location.BK:
                    tempOneWire = Devs.OneWireDevice.BK_Temperature.PIN;
                    if (tempOneWire == null)
                        return tempf;
                    return DS18B20(tempOneWire, tempLocation, debug);

                case Location.MLT:
                    tempOneWire = Devs.OneWireDevice.MLT_Temperature.PIN;
                    if (tempOneWire == null)
                        return tempf;
                    return DS18(tempOneWire, tempLocation, debug);

                case Location.HLT:
                    tempOneWire = Devs.OneWireDevice.HLT_Temperature.PIN;
                    if (tempOneWire == null)
                        return tempf;
                    return DS18B20(tempOneWire, tempLocation, debug);
            }
            return tempf;
        }

        private int DS18B20(OneWire tempOneWire, int tempLocation, bool debug)
        {
            int tempf = BeerDevices.TempError;
            string device = Location.Names[tempLocation];
            if (tempOneWire.Reset())
            {
                tempOneWire.WriteByte(0xCC);
                tempOneWire.WriteByte(0x44);

                while (tempOneWire.ReadByte() == 0)
                {
                    _currentErrorInterval += Interval;
                    if (_currentErrorInterval > ErrorTimeOut)
                    {
                        InvokePanicTriggerEvent(new TriggerMessage("Cannot read temps on onewire device " + device));
                        return tempf;
                    }
                    Thread.Sleep(Interval);
                }

                tempOneWire.Reset();

                // tempOneWire.WriteByte(0x55);
                // tempOneWire.Write(TempProbes.TempProbes[tempLocation].ByteAddress, 0, 8);
                tempOneWire.WriteByte(0xCC);

                tempOneWire.WriteByte(0xBE);
                var whole = (int) tempOneWire.ReadByte(); // LSB
                whole |= (ushort) (tempOneWire.ReadByte() << 8); // MSB
                whole = whole/16;
                tempf = (whole*9)/5 + 32;

                if (debug)
                    BeerProgram.Log("Temperature: " + tempLocation + " " + tempf, LoggingSeverity.Debug);

                tempOneWire.Reset();
            }
            return tempf;
        }

        private int DS18(OneWire tempOneWire, int tempLocation, bool debug)
        {
            var data = new byte[12];
            int tempf = BeerDevices.TempError;
            string device = Location.Names[tempLocation];
            if (tempOneWire.Reset())
            {
                //int owNumber = 0;
                //int i;
                //while (TempOneWire.Search_GetNextDevice(owAddress))
                //{
                //    switch (owNumber)
                //    {
                //        case 0:
                //            if (debug) BeerProgram.Log("Setting HLT Bytes");
                //            for (int index = 0; index < owAddress.Length; index++)
                //            {

                //                HLTTempByte[index] = owAddress[index];
                //            }

                //            break;
                //        case 1:
                //            if (debug) BeerProgram.Log("Setting MLT Bytes");
                //            for (int index = 0; index < owAddress.Length; index++)
                //            {

                //                MLTTempByte[index] = owAddress[index];
                //            }

                //            break;
                //        case 2:
                //            if (debug) BeerProgram.Log("Setting BK Bytes");
                //            for (int index = 0; index < owAddress.Length; index++)
                //            {

                //                BKTempByte[index] = owAddress[index];
                //            }
                //            break;
                //    }

                //    owNumber++;
                //    string st = owAddress[0].ToString();
                //    for (i = 1; i < 8; i++)
                //    {
                //        st += ":" + owAddress[i];
                //    }
                //    if (debug) BeerProgram.Log(st);
                //    //for (i = 0; i < 8; i++) BeerProgram.Log(OW_address[i] + ":");
                //}
                //if (debug) BeerProgram.Log("Found: " + owNumber + " devices");

                //TempOneWire.Reset();


                //tempOneWire.WriteByte(0x55);
                //tempOneWire.Write(TempProbes.TempProbes[tempLocation].ByteAddress, 0, 8);
                tempOneWire.WriteByte(0xCC);
                tempOneWire.WriteByte(0x44);

                while (tempOneWire.ReadByte() == 0)
                {
                    _currentErrorInterval += Interval;
                    if (_currentErrorInterval > ErrorTimeOut)
                    {
                        InvokePanicTriggerEvent(new TriggerMessage("Cannot read temps on onewire device " + device));
                        return tempf;
                    }
                    Thread.Sleep(Interval);
                }

                tempOneWire.Reset();

                // tempOneWire.WriteByte(0x55);
                // tempOneWire.Write(TempProbes.TempProbes[tempLocation].ByteAddress, 0, 8);
                tempOneWire.WriteByte(0xCC);

                tempOneWire.WriteByte(0xBE);

                for (int i = 0; i < 9; i++)
                {
                    data[i] = tempOneWire.ReadByte();
                }
                tempOneWire.Reset();

                ushort temperature = data[0];
                ushort temperature2 = data[1];
                var temperature3 = (ushort) (temperature2 << 8);
                temperature3 += temperature;
                int signbit = temperature3 & 0x8000;
                if (signbit == 1)
                {
                    temperature3 = (ushort) ((temperature3 ^ 0xffff) + 1);
                }

                int tc100 = (temperature3*100/2);
                int whole = tc100/100;
                //int fract = tc100%100;

                //if (fract < 10)
                //    fract = 0;

                tempf = (whole*9)/5 + 32;

                if (debug)
                    BeerProgram.Log("Temperature: " + tempLocation + " " + tempf, LoggingSeverity.Debug);

                tempOneWire.Reset();
            }
            return tempf;
        }
    }

    #endregion
}